﻿/*
 * Test classes for SSAS Partition Manager 
 * https://ssaspartitionmanager.codeplex.com/
 * 
 * Written by Dr. John Tunnicliffe of Decision Analytics, May 2015
 * eMail: john@decision-analytics.co.uk 
 * http://www.decision-analytics.co.uk/
 * https://www.linkedin.com/in/drjohntunnicliffe
 * 
 * Tests written with FluentAssertions, XUnit and Moq which can be installed from Nuget.  
 * 
 * FluentAssertions
 * http://www.fluentassertions.com/ 
 * 
 * XUnit
 * http://xunit.github.io/
 * 
 * Moq
 * https://github.com/Moq/moq4
 */

namespace AmoExtensions.IntegrationTests
{
    using System;
    using System.Collections.Generic;
    using System.Linq;
    using System.Dynamic;
    using AmoExtensions;
    using FluentAssertions;
    using Xunit;
    using Moq;

    /// <summary>
    /// Define the PartitionCollection fixture
    /// </summary>
    [CollectionDefinition("PartitionCollection")]
    public class PartitionCollection : ICollectionFixture<PartitionFixture>
    { }

    /// <summary>
    /// Test the Partition class does what we expect with a real cube
    /// </summary>
    [Collection("PartitionCollection")]
    public class IntegrationTestsPartition 
    {
        /*
         * Here we test if the Partition class does what we expect with a real cube.
         * 
         * We deploy the modified AdventureWorks sample OLAP database using C# to the 
         * local server and then check the functionality of the Partition class.
         * 
         * Note that we mock up the SQL relational interaction by creating the 
         * partition objects by hand.  This gives us better flexibility :-)
         */
        #region Constructor
        public PartitionFixture Fixture { get; set; }

        public IntegrationTestsPartition(PartitionFixture fixture)
        {
            Fixture = fixture;
        }
        #endregion

        #region IsValid
        [Fact]
        public void IsValid_ExistingPartitionShouldReturnTrue()
        {
            Fixture.PartitionExistsAlready.IsValid().Should().Be(true);
        }

        [Fact]
        public void IsValid_ShouldReturnTrue()
        {
            Fixture.PartitionToCreate.IsValid().Should().Be(true);
        }

        [Fact]
        public void IsValid_MgWithNoTemplateShouldThrow()
        {
            Action action = () => Fixture.PartitionInMgWithNoTemplate.IsValid();
            action.ShouldThrow<ApplicationException>();
        }        

        [Fact]
        public void IsValid_InvalidDatabaseShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidDatabase.IsValid();
            action.ShouldThrow<ApplicationException>();
        }

        [Fact]
        public void IsValid_InvalidCubeShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidCube.IsValid();
            action.ShouldThrow<ApplicationException>();
        }

        [Fact]
        public void IsValid_InvalidMeasureGroupShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidMeasureGroup.IsValid();
            action.ShouldThrow<ApplicationException>();
        }
        #endregion

        #region Exists
        [Fact]
        public void Exists_ShouldReturnTrue()
        {
            Fixture.PartitionExistsAlready.Exists().Should().Be(true);
        }

        [Fact]
        public void Exists_ShouldReturnFalse()
        {
            Fixture.PartitionDoesNotExist.Exists().Should().Be(false);
        }

        [Fact]
        public void Exists_InvalidDatabaseShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidDatabase.Exists();
            action.ShouldThrow<ApplicationException>();
        }

        [Fact]
        public void Exists_InvalidCubeShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidCube.Exists();
            action.ShouldThrow<ApplicationException>();
        }

        [Fact]
        public void Exists_InvalidMeasureGroupShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidMeasureGroup.Exists();
            action.ShouldThrow<ApplicationException>();
        }
        #endregion

        #region CreatePartition
        [Fact]
        public void CreatePartition_ShouldReturnTrue()
        {
            Fixture.PartitionToCreate.Create().Should().Be(true);
        }

        [Fact]
        public void CreatePartition_ShouldReturnFalse()
        {
            // returns false as the partition already exists and we did not create it
            Fixture.PartitionExistsAlready.Create().Should().Be(false);
        }

        [Fact]
        public void CreatePartition_InvalidDatabaseShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidDatabase.Create();
            action.ShouldThrow<ApplicationException>();
        }

        [Fact]
        public void CreatePartition_InvalidCubeShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidCube.Create();
            action.ShouldThrow<ApplicationException>();
        }

        [Fact]
        public void CreatePartition_InvalidMeasureGroupShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidMeasureGroup.Create();
            action.ShouldThrow<ApplicationException>();
        }
        #endregion

        #region ProcessPartition
        [Fact]
        public void ProcessPartition_ShouldNotThrow()
        {
            // Use StartCaptureLog / ClearCaptureLog to stop the call to 
            // ProcessPartition actually doing a process of the partition
            Fixture.SsasServer.StartCaptureLog();

            Action action = () => Fixture.PartitionToProcess.Process();
            action.ShouldNotThrow();

            Fixture.SsasServer.ClearCaptureLog();
        }

        [Fact]
        public void ProcessPartition_InvalidDatabaseShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidDatabase.Process();
            action.ShouldThrow<ApplicationException>();
        }

        [Fact]
        public void ProcessPartition_InvalidCubeShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidCube.Process();
            action.ShouldThrow<ApplicationException>();
        }

        [Fact]
        public void ProcessPartition_InvalidMeasureGroupShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidMeasureGroup.Process();
            action.ShouldThrow<ApplicationException>();
        }
        #endregion

        #region DeletePartition
        [Fact]
        public void DeletePartition_ShouldReturnTrue()
        {
            Fixture.PartitionToDelete.Delete().Should().Be(true);
        }

        [Fact]
        public void DeletePartition_ShouldThrowError()
        {
            Action action = () => Fixture.PartitionDoesNotExist.Delete();
            action.ShouldThrow<ApplicationException>();
        }

        [Fact]
        public void DeletePartition_InvalidDatabaseShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidDatabase.Delete();
            action.ShouldThrow<ApplicationException>();
        }

        [Fact]
        public void DeletePartition_InvalidCubeShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidCube.Delete();
            action.ShouldThrow<ApplicationException>();
        }

        [Fact]
        public void DeletePartition_InvalidMeasureGroupShouldThrow()
        {
            Action action = () => Fixture.PartitionWithInvalidMeasureGroup.Delete();
            action.ShouldThrow<ApplicationException>();
        }
        #endregion

        #region Test IsValid and CreatePartition
        [Fact]
        public void CheckIsValidThenCreate_InInternetSales()
        {
            Fixture.PartitionToValidateAndCreate1.IsValid().Should().Be(true);
            Fixture.PartitionToValidateAndCreate1.Create().Should().Be(true);
        }

        [Fact]
        public void CheckIsValidThenCreate_InInternetOrders()
        {
            Fixture.PartitionToValidateAndCreate2.IsValid().Should().Be(true);
            Fixture.PartitionToValidateAndCreate2.Create().Should().Be(true);
        }

        [Fact]
        public void CheckIsValidThenCreate_InInternetCustomers()
        {
            Fixture.PartitionToValidateAndCreate3.IsValid().Should().Be(true);
            Fixture.PartitionToValidateAndCreate3.Create().Should().Be(true);
        }
        #endregion
    }


}
